#!/bin/bash

# 多环境微服务启动脚本
# 支持服务选择、多环境参数和完整的服务管理功能

set -e

# 定义默认值
ENV="dev"
SERVICE="first-case"
ACTION="start"
JAVA_OPTS="-Xms256m -Xmx512m -Dfile.encoding=UTF-8"

# 获取脚本所在目录的绝对路径
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BASE_DIR="$(dirname "$SCRIPT_DIR")"
RUNTIME_DIR="$BASE_DIR/runtime"
ENV_CONFIG_DIR="$BASE_DIR/config"
LOG_DIR="$BASE_DIR/logs"
PID_DIR="$BASE_DIR/pid"
RUNTIME_ENV_DIR="$RUNTIME_DIR/environment"

# 显示帮助信息
show_help() {
  local script_name=$(basename "$0")
  
  echo "============================================"
  echo "           多环境微服务启动脚本帮助            "
  echo "============================================"
  echo "用途: 用于启动、停止和检查微服务的运行状态"
  echo ""
  echo "使用方式:"
  echo "  $script_name [操作选项] [环境选项] [服务选项]"
  echo ""
  echo "操作选项:"
  echo "  --start, -start       启动服务 (默认)"
  echo "  --stop, -stop         停止服务"
  echo "  --status, -status     检查服务状态"
  echo "  -h, --help            显示此帮助信息"
  echo ""
  echo "环境选项:"
  echo "  --env, -env [环境名]  指定运行环境 (默认: dev)"
  echo "                       可选值: dev, test, prod"
  echo ""
  echo "服务选项:"
  echo "  --service, -service [服务名] 指定要操作的服务 (默认: first-case)"
  echo "                       可选值: first-case, second-case"
  echo ""
  echo "JVM选项:"
  echo "  --java-opts [参数]    自定义JVM参数 (可选)"
  echo ""
  echo "示例:"
  echo "  $script_name                       以默认配置启动服务"
  echo "  $script_name -env test            在测试环境启动服务"
  echo "  $script_name -service second-case 启动第二个服务"
  echo "  $script_name -stop                停止服务"
  echo "  $script_name -status              检查服务状态"
  echo "  $script_name -java-opts \"-Xms512m -Xmx1024m\" 自定义JVM参数启动服务"
  echo ""
  echo "============================================"
  exit 0
}

# 解析命令行参数
parse_args() {
  while [[ $# -gt 0 ]]; do
    case "$1" in
      -env|--env)
        if [[ -n "$2" && ! "$2" == -* ]]; then
          # 确保变量赋值正确处理空格
          ENV="$2"
          shift 2
        else
          echo "错误: -env 参数需要一个值"
          show_help
        fi
        ;;
      -service|--service)
        if [[ -n "$2" && ! "$2" == -* ]]; then
          # 确保变量赋值正确处理空格
          SERVICE="$2"
          shift 2
        else
          echo "错误: -service 参数需要一个值"
          show_help
        fi
        ;;
      -action|--action)
        if [[ -n "$2" && ! "$2" == -* ]]; then
          # 确保变量赋值正确处理空格
          ACTION="$2"
          shift 2
        else
          echo "错误: -action 参数需要一个值"
          show_help
        fi
        ;;
      -start|--start)
        ACTION="start"
        shift
        ;;
      -stop|--stop)
        ACTION="stop"
        shift
        ;;
      -status|--status)
        ACTION="status"
        shift
        ;;
      -java-opts|--java-opts)
        if [[ -n "$2" && ! "$2" == -* ]]; then
          # 确保变量赋值正确处理空格
          JAVA_OPTS="$2"
          shift 2
        else
          echo "错误: -java-opts 参数需要一个值"
          show_help
        fi
        ;;
      -h|--help)
        show_help
        ;;
      *)
        echo "错误: 未知参数 '$1'"
        show_help
        ;;
    esac
  done
}

# 调用参数解析函数
parse_args "$@"

# 设置关键路径和文件名
# 确保JAR文件路径正确引用
JAR_FILE="$RUNTIME_DIR/${SERVICE}-1.0-SNAPSHOT.jar"
LOG_FILE="$LOG_DIR/${SERVICE}-${ENV}.log"
PID_FILE="$PID_DIR/${SERVICE}-${ENV}.pid"

# 检查日志目录是否存在，不存在则创建
ensure_log_directory() {
  # 确保日志目录存在
  if [ ! -d "$LOG_DIR" ]; then
    echo "[提示] 日志目录不存在，正在创建: $LOG_DIR"
    mkdir -p "$LOG_DIR"
    echo "[成功] 日志目录已创建"
  fi
  
  # 确保PID目录存在
  if [ ! -d "$PID_DIR" ]; then
    echo "[提示] PID目录不存在，正在创建: $PID_DIR"
    mkdir -p "$PID_DIR"
    echo "[成功] PID目录已创建"
  fi
  
  # 确保运行时环境目录存在
  if [ ! -d "$RUNTIME_ENV_DIR" ]; then
    echo "[提示] 运行时环境目录不存在，正在创建: $RUNTIME_ENV_DIR"
    mkdir -p "$RUNTIME_ENV_DIR"
    echo "[成功] 运行时环境目录已创建"
  fi
}

# 检查服务运行状态
check_service_status() {
  echo ""
  echo "============================================"
  echo "            服务状态检查                        "
  echo "============================================"
  echo "正在检查服务: $SERVICE"
  echo "环境: $ENV"
  
  local is_running=false
  local pid=""
  
  # 检查PID文件
  if [ -f "$PID_FILE" ]; then
    pid=$(cat "$PID_FILE")
    echo "[检查] PID文件中的进程ID: $pid"
    
    # 验证PID是否有效
    if ps -p "$pid" > /dev/null; then
      echo "[状态] 服务正在运行 [PID: $pid]"
      is_running=true
    else
      echo "[警告] PID文件存在但进程不存在，更新状态"
      # 删除无效PID文件
      rm -f "$PID_FILE"
      echo "[操作] 已删除无效PID文件"
    fi
  fi
  
  # 同时检查是否有包含服务名称的Java进程
  if [ "$is_running" = false ]; then
    echo "[检查] 正在查找包含服务名的Java进程"
    # 使用ps命令查找包含服务名的Java进程
    pid=$(ps aux | grep "java" | grep "$SERVICE" | grep -v grep | awk '{print $2}')
    
    if [ -n "$pid" ]; then
      echo "[状态] 服务正在运行 [PID: $pid]"
      is_running=true
      
      # 更新PID文件
      echo "$pid" > "$PID_FILE"
      echo "[操作] 已更新PID文件: $PID_FILE"
    fi
  fi
  
  # 检查JAR文件是否存在
  if [ -f "$JAR_FILE" ]; then
    echo "[检查] JAR文件存在: $JAR_FILE"
  else
    echo "[警告] JAR文件不存在: $JAR_FILE"
  fi
  
  # 显示服务状态摘要
  echo ""
  echo "============================================"
  if [ "$is_running" = true ]; then
    echo "[状态] 服务 $SERVICE (环境: $ENV) 正在运行"
    echo "[提示] 使用命令: $(basename "$0") -stop 停止服务"
  else
    echo "[状态] 服务 $SERVICE (环境: $ENV) 未运行"
    echo "[提示] 使用命令: $(basename "$0") 启动服务"
  fi
  echo "============================================"
  exit 0
}

# 停止服务函数
stop_service() {
  local pid_file_removed=false
  local processes_stopped=false
  
  echo ""
  echo "============================================"
  echo "          服务停止操作                         "
  echo "============================================"
  echo "正在停止服务: $SERVICE"
  
  # 首先检查PID文件
  if [ -f "$PID_FILE" ]; then
    local pid=$(cat "$PID_FILE")
    echo "[检查] 从PID文件读取进程ID: $pid"
    
    # 检查进程是否存在
    if ps -p "$pid" > /dev/null; then
      echo "[操作] 正在终止进程 $pid"
      # 先尝试优雅终止
      kill -15 "$pid" 2>/dev/null
      
      # 等待几秒钟，检查进程是否已终止
      sleep 2
      if ps -p "$pid" > /dev/null; then
        # 如果进程仍在运行，强制终止
        echo "[操作] 进程未响应，尝试强制终止"
        kill -9 "$pid" 2>/dev/null
      fi
      
      if [ ! ps -p "$pid" > /dev/null 2>&1 ]; then
        echo "[成功] 服务进程已终止"
        processes_stopped=true
      else
        echo "[错误] 无法终止进程 $pid"
      fi
    else
      echo "[警告] PID $pid 不存在，删除无效PID文件"
    fi
    
    # 无论进程是否成功终止，都删除PID文件
    rm -f "$PID_FILE"
    echo "[成功] PID文件已删除"
    pid_file_removed=true
  else
    echo "[提示] 未找到PID文件: $PID_FILE"
  fi
  
  # 通过服务名称查找并停止任何剩余的相关进程
  echo "[操作] 正在查找并终止包含服务名的Java进程"
  local pids=$(ps aux | grep "java" | grep "$SERVICE" | grep -v grep | awk '{print $2}')
  
  if [ -n "$pids" ]; then
    for pid in $pids; do
      echo "[操作] 正在终止进程 $pid"
      # 先尝试优雅终止
      kill -15 "$pid" 2>/dev/null
      
      # 等待几秒钟，检查进程是否已终止
      sleep 1
      if ps -p "$pid" > /dev/null; then
        # 如果进程仍在运行，强制终止
        echo "[操作] 进程未响应，尝试强制终止"
        kill -9 "$pid" 2>/dev/null
      fi
      
      if [ ! ps -p "$pid" > /dev/null 2>&1 ]; then
        processes_stopped=true
      fi
    done
    echo "[成功] 已终止所有包含服务名的Java进程"
  else
    echo "[提示] 未找到包含服务名的Java进程"
  fi
  
  # 检查服务是否仍然在运行
  local remaining_pids=$(ps aux | grep "java" | grep "$SERVICE" | grep -v grep | awk '{print $2}')
  
  echo ""
  echo "============================================"
  if [ -z "$remaining_pids" ]; then
    echo "[成功] 服务停止操作已完成"
    echo "[提示] 服务 $SERVICE 已成功停止"
  else
    echo "[警告] 服务停止操作已完成，但仍有进程运行"
    echo "[信息] 剩余进程ID: $remaining_pids"
    echo "[提示] 请手动检查并终止这些进程"
  fi
  
  # 显示下次使用提示
  echo "[提示] 使用命令: $(basename "$0") --status 检查服务状态"
  echo "============================================"
  exit 0
}

# 主函数 - 执行服务启动
execute_start() {
  # 确保日志目录存在
  ensure_log_directory
  
  echo ""
  echo "============================================"
  echo "           服务启动操作                        "
  echo "============================================"
  echo "服务: $SERVICE"
  echo "环境: $ENV"
  echo "============================================"
  
  # 检查运行目录是否存在
  echo ""
  echo "[检查] 正在检查运行目录: $RUNTIME_DIR"
  if [ ! -d "$RUNTIME_DIR" ]; then
    echo "[错误] 运行目录不存在: $RUNTIME_DIR"
    echo "[提示] 请先执行 mvn clean package 构建项目"
    exit 1
  else
    echo "[成功] 运行目录已找到: $RUNTIME_DIR"
  fi
  
  # 检查JAR文件是否存在
  echo "[检查] 正在检查JAR文件: $JAR_FILE"
  if [ ! -f "$JAR_FILE" ]; then
    echo "[错误] JAR文件不存在: $JAR_FILE"
    echo "[提示] 请检查服务名称 '$SERVICE' 是否正确"
    
    # 显示可用的JAR文件
    echo "[提示] 可用的JAR文件:"
    ls -1 "$RUNTIME_DIR"/*.jar 2>/dev/null || echo "  无可用JAR文件"
    
    exit 1
  else
    echo "[成功] JAR文件已找到: $JAR_FILE"
  fi

  # 环境配置文件检查
  echo ""
  echo "[检查] 正在检查环境配置文件"
  
  if [ -d "$ENV_CONFIG_DIR" ]; then
    echo "[成功] 环境配置目录已找到: $ENV_CONFIG_DIR"
  else
    echo "[警告] 环境配置目录不存在: $ENV_CONFIG_DIR"
    echo "[提示] 将使用默认配置启动服务"
  fi
  
  # 确保运行时环境目录存在
  if [ ! -d "$RUNTIME_ENV_DIR" ]; then
    echo "[警告] 运行时环境目录不存在: $RUNTIME_ENV_DIR"
    echo "[提示] 正在创建运行时环境目录"
    mkdir -p "$RUNTIME_ENV_DIR"
    echo "[成功] 运行时环境目录已创建"
  else
    echo "[成功] 运行时环境目录已找到: $RUNTIME_ENV_DIR"
  fi
  
  # 检查Java安装
  echo ""
  echo "[检查] 正在检查Java安装"
  if ! command -v java &> /dev/null; then
    echo "[错误] Java未安装或未在PATH中配置"
    echo "[提示] 请先安装Java并配置环境变量"
    exit 1
  fi
  echo "[成功] Java检测成功"
  
  # 复制环境配置文件
  if [ -d "$ENV_CONFIG_DIR/$ENV" ]; then
    echo ""
    echo "[检查] 正在复制环境配置文件: $ENV_CONFIG_DIR/$ENV/*"
    cp -f "$ENV_CONFIG_DIR/$ENV"/* "$RUNTIME_ENV_DIR" 2>/dev/null
    if [ $? -eq 0 ]; then
      echo "[成功] 环境配置文件已成功复制到运行时目录"
    else
      echo "[警告] 复制环境配置文件失败，将使用默认配置启动"
    fi
  else
    echo ""
    echo "[警告] 未找到环境配置: $ENV_CONFIG_DIR/$ENV"
  fi
  
  # 准备启动命令
  local SPRING_PROFILES_ACTIVE="$ENV"
  local CONFIG_LOCATIONS="--spring.config.location=classpath:/,file:../environment/,file:../runtime/environment/"
  
  # 检查服务是否已在运行
  if [ -f "$PID_FILE" ]; then
    local pid=$(cat "$PID_FILE")
    if ps -p "$pid" > /dev/null; then
      echo ""
      echo "[警告] 服务 $SERVICE 已经在运行 [PID: $pid]"
      echo "[提示] 使用命令: $(basename "$0") -stop 先停止现有服务"
      exit 1
    fi
    # 删除无效的PID文件
    rm -f "$PID_FILE"
  fi
  
  # 显示启动信息
  echo ""
  echo "============================================"
  echo "即将启动服务: $SERVICE"
  echo "环境: $ENV"
  echo "JAR文件: $JAR_FILE"
  echo "日志文件: $LOG_FILE"
  echo "JVM参数: $JAVA_OPTS"
  echo "============================================"
  
  # 启动Java应用
  echo ""
  echo "[操作] 正在启动服务..."
  echo "[命令] java $JAVA_OPTS -Dspring.profiles.active=$SPRING_PROFILES_ACTIVE -jar \"$JAR_FILE\" $CONFIG_LOCATIONS"
  
  # 使用nohup在后台启动服务并记录日志
  nohup java $JAVA_OPTS -Dspring.profiles.active=$SPRING_PROFILES_ACTIVE -jar "$JAR_FILE" $CONFIG_LOCATIONS > "$LOG_FILE" 2>&1 &
  
  # 获取进程PID
  local pid=$!
  
  # 记录PID到PID文件
  echo "$pid" > "$PID_FILE"
  
  # 等待服务启动
  echo ""
  echo "[操作] 服务正在启动，记录PID: $pid"
  echo "[操作] 日志输出: $LOG_FILE"
  
  # 检查服务是否成功启动
  sleep 2
  if ps -p "$pid" > /dev/null; then
    echo ""
    echo "============================================"
    echo "[成功] 服务 $SERVICE (环境: $ENV) 已成功启动"
    echo "[信息] PID: $pid"
    echo "[提示] 使用命令: $(basename "$0") -status 检查服务状态"
    echo "[提示] 使用命令: $(basename "$0") -stop 停止服务"
    echo "============================================"
  else
    echo ""
    echo "============================================"
    echo "[错误] 服务启动失败，请检查日志: $LOG_FILE"
    echo "============================================"
    rm -f "$PID_FILE"
    exit 1
  fi
}

# 根据操作类型执行相应功能
case "$ACTION" in
  stop)
    stop_service
    ;;
  status)
    check_service_status
    ;;
  start)
    execute_start
    ;;
  *)
    echo "错误: 未知操作 '$ACTION'"
    show_help
    ;;
esac